#ifndef __M_REACTOR_H__
#define __M_REACTOR_H__

#include <memory>
#include "Epoll.hpp"
#include "Socket.hpp"
#include "EventUnit.hpp"
#include <unordered_map>

class Reactor {
    public:
        static const int revs_num = 128;
        static const int default_timeout = 1000;

        Reactor() 
            :_epoller(std::make_shared<Epoller>())
            ,_isrunning(false)
        {}

        // 主循环
        void loop() {
            _isrunning = true;
            while(_isrunning) {
                Dispatcher(default_timeout);
            }
        }

        // 进行事件监控
        void Dispatcher(int timeout) {
            // 等待事件 返回就绪的事件数量
            int n = _epoller->WaitEvent(_revs, revs_num, timeout);

            for(int i = 0; i < n; i++) {
                int sockfd = _revs[i].data.fd;
                int revents = _revs[i].events;
                EventUnit ev = _events[sockfd];
                
                // 先处理异常
                if((revents & EPOLLERR) || (revents & EPOLLHUP)) {
                    ev._error(&ev);
                }

                // 读事件就绪
                if(revents & EPOLLIN) {
                    ev._recver(&ev);
                }

                // 写事件就绪
                if(revents & EPOLLOUT) {
                    ev._sender(&ev);
                }
            }
        }

        void EnableReadWrite(int sockfd, bool read, bool write) {
            uint32_t new_events = (EPOLLET | (read ? EPOLLIN : 0) | (write ? EPOLLOUT : 0));
            _epoller->ModEvent(sockfd, new_events);
        }

        void AddEvent(int sockfd, uint32_t event, const EventUnit& ev) {
            _epoller->AddEvent(sockfd, event);
            _events.insert(std::make_pair(sockfd, ev));
            std::cout << "添加：" << sockfd << " 到epoll模型中" << std::endl; 
        }

        void DelEvent(int sockfd) {
            _epoller->delEvent(sockfd);
            _events.erase(sockfd);
        }

        void Stop() {
            _isrunning = false;
        }
        
    private:
        std::shared_ptr<Epoller> _epoller;
        struct epoll_event _revs[revs_num];
        std::unordered_map<int, EventUnit> _events;
        bool _isrunning;
};


#endif